#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Flask学生管理系统
使用MongoDB作为后端数据库
"""

from flask import Flask, render_template, request, jsonify, redirect, url_for, flash, session
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
from bson.objectid import ObjectId
from datetime import datetime
import os
import pandas as pd
from werkzeug.utils import secure_filename
import tempfile
import re
import logging
from dotenv import load_dotenv
import magic
import bcrypt
from functools import wraps

# 加载环境变量
load_dotenv()

app = Flask(__name__)
app.secret_key = os.getenv('SECRET_KEY', 'fallback-secret-key-change-in-production')

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 文件上传配置
UPLOAD_FOLDER = os.getenv('UPLOAD_FOLDER', 'uploads')
ALLOWED_EXTENSIONS = {'xlsx', 'xls', 'csv'}
ALLOWED_IMAGE_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = int(os.getenv('MAX_CONTENT_LENGTH', 16 * 1024 * 1024))
app.config['MAX_IMAGE_SIZE'] = int(os.getenv('MAX_IMAGE_SIZE', 2 * 1024 * 1024))

# 创建上传目录
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(os.path.join(UPLOAD_FOLDER, 'photos'), exist_ok=True)

# MongoDB连接配置
MONGO_URI = os.getenv('MONGO_URI', "mongodb://localhost:27017/")
DB_NAME = os.getenv('DB_NAME', "student_management")
COLLECTION_NAME = os.getenv('COLLECTION_NAME', "students")
COURSES_COLLECTION = os.getenv('COURSES_COLLECTION', "courses")
STUDENT_COURSES_COLLECTION = os.getenv('STUDENT_COURSES_COLLECTION', "student_courses")
ADMIN_USERS_COLLECTION = os.getenv('ADMIN_USERS_COLLECTION', "admin_users")
STUDENT_AUTH_COLLECTION = os.getenv('STUDENT_AUTH_COLLECTION', "student_auth")

# 初始化MongoDB连接
def get_db_connection():
    try:
        client = MongoClient(MONGO_URI)
        db = client[DB_NAME]
        return db
    except ConnectionFailure as e:
        print(f"MongoDB连接失败: {e}")
        return None

def get_students_collection():
    db = get_db_connection()
    if db is not None:
        return db[COLLECTION_NAME]
    return None

def get_courses_collection():
    db = get_db_connection()
    if db is not None:
        return db[COURSES_COLLECTION]
    return None

def get_student_courses_collection():
    db = get_db_connection()
    if db is not None:
        return db[STUDENT_COURSES_COLLECTION]
    return None

def get_admin_users_collection():
    db = get_db_connection()
    if db is not None:
        return db[ADMIN_USERS_COLLECTION]
    return None

def get_student_auth_collection():
    db = get_db_connection()
    if db is not None:
        return db[STUDENT_AUTH_COLLECTION]
    return None

def hash_password(password):
    """使用bcrypt加密密码"""
    return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

def check_password(password, hashed):
    """验证密码"""
    return bcrypt.checkpw(password.encode('utf-8'), hashed.encode('utf-8'))

def init_super_admin():
    """初始化超级管理员账号"""
    collection = get_admin_users_collection()
    if collection is None:
        return False
    
    # 检查是否已存在超级管理员
    existing_admin = collection.find_one({'username': 'admin'})
    if existing_admin:
        return True
    
    # 创建超级管理员
    admin_data = {
        'username': 'admin',
        'password': hash_password('12345678'),
        'role': 'super_admin',
        'created_at': datetime.now(),
        'updated_at': datetime.now(),
        'last_login': None
    }
    
    try:
        collection.insert_one(admin_data)
        return True
    except Exception as e:
        logger.error(f"初始化超级管理员失败: {str(e)}")
        return False

def create_student_auth_account(student_id, phone, name):
    """自动创建学生认证账号"""
    collection = get_student_auth_collection()
    if collection is None:
        logger.error("无法连接到学生认证集合")
        return False
    
    # 检查是否已存在该学生的认证账号
    existing_account = collection.find_one({'student_id': ObjectId(student_id)})
    if existing_account:
        logger.info(f"学生 {name} 的认证账号已存在")
        return True
    
    # 创建学生认证账号
    auth_data = {
        'student_id': ObjectId(student_id),
        'username': phone,  # 使用手机号作为用户名
        'password': hash_password(phone[-6:]),  # 使用手机号后6位作为初始密码
        'name': name,
        'created_at': datetime.now(),
        'updated_at': datetime.now(),
        'last_login': None,
        'status': 'active'
    }
    
    try:
        collection.insert_one(auth_data)
        logger.info(f"已为学生 {name} 创建认证账号，用户名: {phone}, 初始密码: {phone[-6:]}")
        return True
    except Exception as e:
        logger.error(f"创建学生认证账号失败: {str(e)}")
        return False

def get_dynamic_fields(student):
    """从学生数据中提取动态字段（排除系统字段）"""
    system_fields = ['_id', 'name', 'age', 'gender', 'grade', 'major', 'email', 'phone', 'created_at', 'updated_at', 'photo']
    dynamic_fields = {}
    
    for field, value in student.items():
        if field not in system_fields:
            # 转换ObjectId为字符串以便JSON序列化
            if isinstance(value, ObjectId):
                dynamic_fields[field] = str(value)
            else:
                dynamic_fields[field] = value
    
    return dynamic_fields

def allowed_file(filename):
    """检查文件扩展名是否允许"""
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def allowed_image(filename):
    """检查图片文件扩展名是否允许"""
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_IMAGE_EXTENSIONS

def validate_email(email):
    """验证邮箱格式"""
    if not email:
        return True
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None

def validate_phone(phone):
    """验证手机号格式"""
    if not phone:
        return True
    pattern = r'^1[3-9]\d{9}$'  # 中国手机号格式
    return re.match(pattern, phone) is not None

def is_valid_file(file_stream):
    """使用magic库检测文件真实类型"""
    try:
        file_type = magic.from_buffer(file_stream.read(1024))
        file_stream.seek(0)
        return 'Excel' in file_type or 'CSV' in file_type or 'text' in file_type
    except:
        return False

class AppError(Exception):
    """自定义应用异常"""
    def __init__(self, message, status_code=400):
        super().__init__(message)
        self.status_code = status_code
        self.message = message

def parse_student_file(file_path, file_extension):
    """解析学生信息文件 - 支持所有字段"""
    try:
        if file_extension in ['xlsx', 'xls']:
            df = pd.read_excel(file_path)
        elif file_extension == 'csv':
            df = pd.read_csv(file_path)
        else:
            return None, "不支持的文件格式"
        
        # 检查必要的列
        required_columns = ['姓名', '年龄', '电话']
        for col in required_columns:
            if col not in df.columns:
                return None, f"缺少必要列: {col}"
        
        # 字段名映射（中文到英文）
        field_mapping = {
            '姓名': 'name',
            '年龄': 'age', 
            '性别': 'gender',
            '年级': 'grade',
            '专业': 'major',
            '邮箱': 'email',
            '电话': 'phone'
        }
        
        # 转换数据 - 支持所有字段
        students = []
        for _, row in df.iterrows():
            # 跳过空行（姓名、年龄和电话为必填）
            if pd.isna(row['姓名']) or pd.isna(row['年龄']) or pd.isna(row['电话']):
                continue
                
            # 验证手机号格式
            phone = str(row['电话']).strip()
            if not validate_phone(phone):
                return None, f"手机号格式错误: {phone} (行: {_ + 2})"
                
            student_data = {}
            
            # 处理所有列
            for col_name, value in row.items():
                if pd.notna(value):  # 只处理非空值
                    # 使用映射字段名或保留原始字段名
                    field_name = field_mapping.get(col_name, col_name)
                    # 转换数据类型
                    if col_name == '年龄':
                        student_data[field_name] = int(value)
                    else:
                        student_data[field_name] = str(value).strip()
            
            # 添加时间戳
            student_data['created_at'] = datetime.now()
            student_data['updated_at'] = datetime.now()
            
            students.append(student_data)
        
        return students, None
        
    except Exception as e:
        return None, f"文件解析错误: {str(e)}"

# 登录装饰器
def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if 'user_id' not in session:
            flash('请先登录', 'error')
            return redirect(url_for('login'))
        return f(*args, **kwargs)
    return decorated_function

def admin_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if 'user_id' not in session:
            flash('请先登录', 'error')
            return redirect(url_for('login'))
        if session.get('role') != 'super_admin':
            flash('需要管理员权限', 'error')
            return redirect(url_for('index'))
        return f(*args, **kwargs)
    return decorated_function

# 路由定义
@app.route('/login', methods=['GET', 'POST'])
def login():
    """用户登录 - 支持管理员和学生"""
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        
        if not username or not password:
            flash('用户名和密码不能为空', 'error')
            return render_template('login.html')
        
        # 首先检查管理员用户
        admin_collection = get_admin_users_collection()
        if admin_collection is not None:
            admin_user = admin_collection.find_one({'username': username})
            if admin_user and check_password(password, admin_user['password']):
                # 管理员登录成功
                session['user_id'] = str(admin_user['_id'])
                session['username'] = admin_user['username']
                session['role'] = admin_user['role']
                session['user_type'] = 'admin'
                
                # 更新最后登录时间
                admin_collection.update_one(
                    {'_id': admin_user['_id']},
                    {'$set': {'last_login': datetime.now()}}
                )
                
                flash(f'欢迎回来，{admin_user["username"]}!', 'success')
                return redirect(url_for('index'))
        
        # 如果不是管理员，检查学生用户
        student_auth_collection = get_student_auth_collection()
        if student_auth_collection is not None:
            student_user = student_auth_collection.find_one({'username': username})
            if student_user and check_password(password, student_user['password']):
                # 学生登录成功
                session['user_id'] = str(student_user['_id'])
                session['username'] = student_user['username']
                session['name'] = student_user['name']
                session['user_type'] = 'student'
                session['role'] = 'student'  # 设置角色为学生
                
                # 更新最后登录时间
                student_auth_collection.update_one(
                    {'_id': student_user['_id']},
                    {'$set': {'last_login': datetime.now()}}
                )
                
                flash(f'欢迎回来，{student_user["name"]}同学!', 'success')
                return redirect(url_for('student_dashboard'))
        
        # 如果都不是，登录失败
        flash('用户名或密码错误', 'error')
        return render_template('login.html')
    
    return render_template('login.html')

@app.route('/logout')
def logout():
    """用户登出"""
    session.clear()
    flash('您已成功登出', 'success')
    return redirect(url_for('login'))

@app.route('/')
@login_required
def index():
    """首页 - 根据用户类型显示不同内容"""
    if session.get('user_type') == 'student':
        # 学生显示学生个人主页
        return redirect(url_for('student_dashboard'))
    else:
        # 管理员显示综合仪表板
        return redirect(url_for('admin_dashboard'))

@app.route('/add', methods=['GET', 'POST'])
@login_required
def add_student():
    """添加学生"""
    if request.method == 'POST':
        # 获取表单数据
        name = request.form.get('name')
        age = request.form.get('age')
        gender = request.form.get('gender')
        grade = request.form.get('grade')
        major = request.form.get('major')
        email = request.form.get('email')
        phone = request.form.get('phone')
        
        # 获取动态字段数据
        field_names = request.form.getlist('field_names[]')
        field_values = request.form.getlist('field_values[]')
        
        # 验证必填字段
        if not name or not age or not phone:
            flash('姓名、年龄和电话是必填项', 'error')
            return render_template('add.html')
        
        # 验证手机号格式
        if not validate_phone(phone):
            flash('手机号格式不正确，请输入有效的中国手机号', 'error')
            return render_template('add.html')
        
        # 创建学生数据
        student_data = {
            'name': name,
            'age': int(age),
            'gender': gender,
            'grade': grade,
            'major': major,
            'email': email,
            'phone': phone,
            'created_at': datetime.now(),
            'updated_at': datetime.now()
        }
        
        # 添加动态字段到学生数据
        for name, value in zip(field_names, field_values):
            if name and name.strip():  # 确保字段名不为空
                student_data[name.strip()] = value.strip()
        
        # 插入数据库
        collection = get_students_collection()
        if collection is not None:
            result = collection.insert_one(student_data)
            
            # 自动创建学生认证账号
            create_student_auth_account(str(result.inserted_id), phone, name)
            
            flash('学生添加成功!', 'success')
            return redirect(url_for('index'))
        else:
            flash('数据库连接失败', 'error')
            return render_template('add.html')
    
    return render_template('add.html')

@app.route('/edit/<student_id>', methods=['GET', 'POST'])
@login_required
def edit_student(student_id):
    """编辑学生信息"""
    collection = get_students_collection()
    if collection is None:
        flash('数据库连接失败', 'error')
        return redirect(url_for('index'))
    
    # 获取学生信息
    student = collection.find_one({'_id': ObjectId(student_id)})
    if not student:
        flash('学生不存在', 'error')
        return redirect(url_for('index'))
    
    if request.method == 'POST':
        # 获取表单数据
        name = request.form.get('name')
        age = request.form.get('age')
        gender = request.form.get('gender')
        grade = request.form.get('grade')
        major = request.form.get('major')
        email = request.form.get('email')
        phone = request.form.get('phone')
        
        # 获取动态字段数据
        field_names = request.form.getlist('field_names[]')
        field_values = request.form.getlist('field_values[]')
        
        # 验证必填字段
        if not name or not age or not phone:
            flash('姓名、年龄和电话是必填项', 'error')
            return render_template('edit.html', student=student)
        
        # 验证手机号格式
        if not validate_phone(phone):
            flash('手机号格式不正确，请输入有效的中国手机号', 'error')
            return render_template('edit.html', student=student)
        
        # 更新数据
        update_data = {
            'name': name,
            'age': int(age),
            'gender': gender,
            'grade': grade,
            'major': major,
            'email': email,
            'phone': phone,
            'updated_at': datetime.now()
        }
        
        # 添加动态字段到更新数据
        for name, value in zip(field_names, field_values):
            if name and name.strip():  # 确保字段名不为空
                update_data[name.strip()] = value.strip()
        
        # 更新数据库
        collection.update_one(
            {'_id': ObjectId(student_id)},
            {'$set': update_data}
        )
        
        # 同步更新student_auth表中的信息
        student_auth_collection = get_student_auth_collection()
        if student_auth_collection is not None:
            # 检查是否需要更新student_auth表（姓名或电话有变化）
            old_phone = student.get('phone', '')
            old_name = student.get('name', '')
            
            if phone != old_phone or name != old_name:
                auth_update_data = {
                    'updated_at': datetime.now()
                }
                
                # 如果电话有变化，更新用户名
                if phone != old_phone:
                    auth_update_data['username'] = phone
                
                # 如果姓名有变化，更新姓名
                if name != old_name:
                    auth_update_data['name'] = name
                
                # 更新student_auth表
                student_auth_collection.update_one(
                    {'student_id': ObjectId(student_id)},
                    {'$set': auth_update_data}
                )
        
        flash('学生信息更新成功!', 'success')
        return redirect(url_for('index'))
    
    return render_template('edit.html', student=student)

@app.route('/delete/<student_id>')
@login_required
def delete_student(student_id):
    """删除学生"""
    collection = get_students_collection()
    if collection is not None:
        result = collection.delete_one({'_id': ObjectId(student_id)})
        if result.deleted_count > 0:
            flash('学生删除成功!', 'success')
        else:
            flash('学生不存在', 'error')
    else:
        flash('数据库连接失败', 'error')
    
    return redirect(url_for('index'))

@app.route('/import', methods=['GET', 'POST'])
@login_required
def import_students():
    """导入学生信息"""
    if request.method == 'POST':
        # 检查是否有文件上传
        if 'file' not in request.files:
            flash('请选择要上传的文件', 'error')
            return redirect(request.url)
        
        file = request.files['file']
        
        # 检查文件名
        if file.filename == '':
            flash('请选择要上传的文件', 'error')
            return redirect(request.url)
        
        # 检查文件类型
        if not allowed_file(file.filename):
            flash('只支持 Excel (.xlsx, .xls) 和 CSV 文件', 'error')
            return redirect(request.url)
        
        # 保存文件
        original_filename = file.filename
        if '.' not in original_filename:
            flash('文件缺少扩展名', 'error')
            return redirect(request.url)
        
        filename = secure_filename(original_filename)
        file_extension = original_filename.rsplit('.', 1)[1].lower()
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(file_path)
        
        # 解析文件
        students, error = parse_student_file(file_path, file_extension)
        
        if error:
            flash(f'文件解析失败: {error}', 'error')
            # 删除临时文件
            if os.path.exists(file_path):
                os.remove(file_path)
            return redirect(request.url)
        
        if not students:
            flash('文件中没有找到有效的学生数据', 'warning')
            # 删除临时文件
            if os.path.exists(file_path):
                os.remove(file_path)
            return redirect(request.url)
        
        # 插入数据库
        collection = get_students_collection()
        if collection is not None:
            try:
                # 检查重复数据
                existing_names = {student['name'] for student in collection.find({}, {'name': 1})}
                new_students = [student for student in students if student['name'] not in existing_names]
                
                if new_students:
                    result = collection.insert_many(new_students)
                    flash(f'成功导入 {len(result.inserted_ids)} 名学生信息!', 'success')
                    if len(students) > len(new_students):
                        flash(f'跳过 {len(students) - len(new_students)} 名已存在的学生', 'warning')
                else:
                    flash('所有学生数据已存在，没有新数据导入', 'warning')
            except Exception as e:
                flash(f'数据导入失败: {str(e)}', 'error')
        else:
            flash('数据库连接失败', 'error')
        
        # 删除临时文件
        if os.path.exists(file_path):
            os.remove(file_path)
        
        return redirect(url_for('index'))
    
    return render_template('import.html')

@app.route('/api/students', methods=['GET'])
@login_required
def api_students():
    """API接口 - 获取所有学生"""
    # 权限验证：只有管理员可以查看所有学生
    if session.get('user_type') != 'admin':
        return jsonify({'error': '权限不足，需要管理员权限'}), 403
    
    collection = get_students_collection()
    if collection is not None:
        students = list(collection.find().sort('created_at', -1))
        # 转换ObjectId为字符串
        for student in students:
            student['_id'] = str(student['_id'])
        return jsonify(students)
    return jsonify([])

@app.route('/api/students/<student_id>', methods=['GET'])
@login_required
def api_student_detail(student_id):
    """API接口 - 获取单个学生详情"""
    # 权限验证：学生只能查看自己的信息，管理员可以查看所有
    user_type = session.get('user_type')
    
    if user_type == 'student':
        # 学生只能查看自己的信息
        student_auth_collection = get_student_auth_collection()
        if student_auth_collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        # 获取当前登录学生的认证信息
        student_auth = student_auth_collection.find_one({'_id': ObjectId(session.get('user_id'))})
        if not student_auth:
            return jsonify({'error': '学生认证信息不存在'}), 404
        
        # 验证学生ID是否匹配
        if str(student_auth['student_id']) != student_id:
            return jsonify({'error': '无权查看其他学生的信息'}), 403
    
    collection = get_students_collection()
    if collection is not None:
        try:
            student = collection.find_one({'_id': ObjectId(student_id)})
            if student:
                student['_id'] = str(student['_id'])
                return jsonify(student)
            else:
                return jsonify({'error': '学生不存在'}), 404
        except Exception as e:
            return jsonify({'error': '无效的学生ID'}), 400
    return jsonify({'error': '数据库连接失败'}), 500

# 注册模板全局函数
@app.context_processor
def utility_processor():
    return dict(get_dynamic_fields=get_dynamic_fields)

# 错误处理
@app.errorhandler(AppError)
def handle_app_error(error):
    logger.error(f"AppError: {error.message}")
    return jsonify({'error': error.message}), error.status_code

@app.errorhandler(Exception)
def handle_general_error(error):
    logger.error(f"Unexpected error: {str(error)}")
    return jsonify({'error': '服务器内部错误'}), 500

@app.errorhandler(404)
def not_found(error):
    return render_template('404.html'), 404

# 搜索功能
@app.route('/search')
def search_students():
    """搜索学生"""
    query = request.args.get('q', '')
    page = int(request.args.get('page', 1))
    per_page = int(request.args.get('per_page', 10))
    
    collection = get_students_collection()
    if collection is None:
        return jsonify({'error': '数据库连接失败'}), 500
    
    # 构建搜索条件
    search_conditions = {}
    if query:
        search_conditions = {
            '$or': [
                {'name': {'$regex': query, '$options': 'i'}},
                {'major': {'$regex': query, '$options': 'i'}},
                {'grade': {'$regex': query, '$options': 'i'}},
                {'email': {'$regex': query, '$options': 'i'}}
            ]
        }
    
    # 分页查询
    skip = (page - 1) * per_page
    students = list(collection.find(search_conditions)
                  .skip(skip)
                  .limit(per_page)
                  .sort('created_at', -1))
    
    total = collection.count_documents(search_conditions)
    
    # 转换ObjectId为字符串
    for student in students:
        student['_id'] = str(student['_id'])
    
    return jsonify({
        'students': students,
        'total': total,
        'page': page,
        'per_page': per_page,
        'total_pages': (total + per_page - 1) // per_page
    })

# 数据统计
@app.route('/api/stats')
def get_statistics():
    """获取统计数据API"""
    try:
        collection = get_students_collection()
        if collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        # 按性别统计 - 处理空值和不同格式
        gender_stats = list(collection.aggregate([
            {'$match': {'gender': {'$exists': True, '$ne': ''}}},  # 排除空字符串
            {'$group': {'_id': '$gender', 'count': {'$sum': 1}}}
        ]))
        
        # 按年级统计 - 处理空值
        grade_stats = list(collection.aggregate([
            {'$match': {'grade': {'$exists': True, '$ne': ''}}},  # 排除空字符串
            {'$group': {'_id': '$grade', 'count': {'$sum': 1}}}
        ]))
        
        # 年龄分布 - 确保年龄字段存在且为数字
        age_stats = list(collection.aggregate([
            {'$match': {'age': {'$exists': True, '$type': 'number'}}},  # 确保年龄是数字类型
            {'$group': {'_id': '$age', 'count': {'$sum': 1}}},
            {'$sort': {'_id': 1}}
        ]))
        
        # 获取选课统计信息
        course_stats = get_course_statistics()
        
        # 获取学生选课统计
        student_course_stats = get_student_course_statistics()
        
        # 统一性别格式（将英文转换为中文）
        unified_gender_stats = []
        gender_mapping = {
            'male': '男',
            'female': '女',
            'Male': '男',
            'Female': '女',
            'M': '男',
            'F': '女'
        }
        
        for gender_stat in gender_stats:
            gender_id = gender_stat['_id']
            # 如果性别在映射表中，使用映射后的值
            if gender_id in gender_mapping:
                mapped_gender = gender_mapping[gender_id]
                # 检查是否已经存在该性别的统计
                existing = next((item for item in unified_gender_stats if item['_id'] == mapped_gender), None)
                if existing:
                    existing['count'] += gender_stat['count']
                else:
                    unified_gender_stats.append({'_id': mapped_gender, 'count': gender_stat['count']})
            else:
                # 不在映射表中的性别直接保留
                unified_gender_stats.append(gender_stat)
        
        return jsonify({
            'gender': unified_gender_stats,
            'grade': grade_stats,
            'age': age_stats,
            'total': collection.count_documents({}),
            'course_stats': course_stats,
            'student_course_stats': student_course_stats
        })
        
    except Exception as e:
        logger.error(f"统计API错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

def get_course_statistics():
    """获取课程选课统计信息"""
    try:
        courses_collection = get_courses_collection()
        student_courses_collection = get_student_courses_collection()
        
        if courses_collection is None or student_courses_collection is None:
            return {}
        
        # 获取所有课程
        courses = list(courses_collection.find())
        
        # 获取每个课程的选课人数
        course_enrollment = []
        for course in courses:
            enrollment_count = student_courses_collection.count_documents({
                'course_id': course['_id']
            })
            
            course_enrollment.append({
                'course_id': str(course['_id']),
                'course_code': course.get('course_code', ''),
                'course_name': course.get('course_name', ''),
                'capacity': course.get('capacity', 0),
                'enrolled': enrollment_count,
                'enrollment_rate': round((enrollment_count / course['capacity']) * 100, 1) if course.get('capacity', 0) > 0 else 0
            })
        
        # 按选课人数排序
        course_enrollment.sort(key=lambda x: x['enrolled'], reverse=True)
        
        # 计算总体统计
        total_courses = len(courses)
        total_enrollment = sum(course['enrolled'] for course in course_enrollment)
        avg_enrollment = round(total_enrollment / total_courses, 1) if total_courses > 0 else 0
        
        # 找出热门课程（前5名）
        popular_courses = course_enrollment[:5]
        
        # 找出空闲课程（选课率为0的课程）
        available_courses = [course for course in course_enrollment if course['enrolled'] == 0]
        
        return {
            'total_courses': total_courses,
            'total_enrollment': total_enrollment,
            'avg_enrollment': avg_enrollment,
            'popular_courses': popular_courses,
            'available_courses': available_courses,
            'course_enrollment': course_enrollment
        }
        
    except Exception as e:
        logger.error(f"获取课程统计错误: {str(e)}")
        return {}

def get_student_course_statistics():
    """获取学生选课统计信息"""
    try:
        students_collection = get_students_collection()
        student_courses_collection = get_student_courses_collection()
        
        if students_collection is None or student_courses_collection is None:
            return {}
        
        # 获取所有学生
        total_students = students_collection.count_documents({})
        
        # 获取每个学生的选课数量
        pipeline = [
            {
                '$group': {
                    '_id': '$student_id',
                    'course_count': {'$sum': 1}
                }
            }
        ]
        
        student_course_counts = list(student_courses_collection.aggregate(pipeline))
        
        if not student_course_counts:
            return {
                'avg_courses_per_student': 0,
                'max_courses': 0,
                'min_courses': 0,
                'students_with_courses': 0,
                'total_course_selections': 0
            }
        
        # 计算统计指标
        course_counts = [item['course_count'] for item in student_course_counts]
        total_course_selections = sum(course_counts)
        avg_courses = round(total_course_selections / len(student_course_counts), 1)
        max_courses = max(course_counts)
        min_courses = min(course_counts)
        
        # 选课分布
        distribution = {}
        for count in course_counts:
            distribution[count] = distribution.get(count, 0) + 1
        
        # 转换为排序后的列表
        distribution_list = [{'courses': k, 'students': v} for k, v in distribution.items()]
        distribution_list.sort(key=lambda x: x['courses'])
        
        return {
            'avg_courses_per_student': avg_courses,
            'max_courses': max_courses,
            'min_courses': min_courses,
            'students_with_courses': len(student_course_counts),
            'total_course_selections': total_course_selections,
            'distribution': distribution_list,
            'participation_rate': round((len(student_course_counts) / total_students) * 100, 1) if total_students > 0 else 0
        }
        
    except Exception as e:
        logger.error(f"获取学生选课统计错误: {str(e)}")
        return {}

# 导出功能
@app.route('/export/excel')
@login_required
def export_excel():
    """导出Excel文件"""
    collection = get_students_collection()
    if collection is None:
        raise AppError('数据库连接失败', 500)
    
    students = list(collection.find())
    
    # 创建DataFrame
    df = pd.DataFrame(students)
    
    # 移除_id字段
    if '_id' in df.columns:
        df.drop('_id', axis=1, inplace=True)
    
    # 创建内存中的Excel文件
    from io import BytesIO
    output = BytesIO()
    with pd.ExcelWriter(output, engine='openpyxl') as writer:
        df.to_excel(writer, index=False, sheet_name='学生信息')
    
    output.seek(0)
    
    from flask import send_file
    return send_file(output, 
                    download_name='学生信息导出.xlsx',
                    as_attachment=True,
                    mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')

# 照片上传
@app.route('/upload_photo/<student_id>', methods=['POST'])
@login_required
def upload_photo(student_id):
    """上传学生照片"""
    if 'photo' not in request.files:
        raise AppError('请选择照片文件')
    
    file = request.files['photo']
    if file.filename == '':
        raise AppError('请选择照片文件')
    
    if not allowed_image(file.filename):
        raise AppError('只支持PNG, JPG, JPEG, GIF格式的图片')
    
    # 检查文件大小
    file_data = file.read()
    if len(file_data) > app.config['MAX_IMAGE_SIZE']:
        raise AppError('图片大小不能超过2MB')
    
    # 保存照片
    file_extension = file.filename.rsplit('.', 1)[1].lower()
    filename = f"{student_id}.{file_extension}"
    file_path = os.path.join(app.config['UPLOAD_FOLDER'], 'photos', filename)
    
    # 写入文件
    with open(file_path, 'wb') as f:
        f.write(file_data)
    
    # 更新数据库
    collection = get_students_collection()
    if collection is None:
        raise AppError('数据库连接失败', 500)
    
    collection.update_one(
        {'_id': ObjectId(student_id)},
        {'$set': {'photo': filename}}
    )
    
    return jsonify({'message': '照片上传成功', 'filename': filename})

@app.route('/statistics')
@login_required
def statistics():
    """统计页面"""
    return render_template('statistics.html')

# 课程管理功能
@app.route('/courses')
@login_required
def courses():
    """课程列表页面"""
    return render_template('courses.html')

@app.route('/selection')
@login_required
def selection():
    """选课页面"""
    return render_template('selection.html')

@app.route('/my-courses')
@login_required
def my_courses():
    """我的课程页面"""
    return render_template('my_courses.html')

@app.route('/student-dashboard')
@login_required
def student_dashboard():
    """学生个人主页"""
    # 检查用户类型，只有学生可以访问
    if session.get('user_type') != 'student':
        flash('无权访问学生页面', 'error')
        return redirect(url_for('index'))
    
    return render_template('student_dashboard.html')

@app.route('/admin-dashboard')
@login_required
def admin_dashboard():
    """管理员综合仪表板"""
    # 检查用户类型，只有管理员可以访问
    if session.get('user_type') == 'student':
        flash('无权访问管理员页面', 'error')
        return redirect(url_for('student_dashboard'))
    
    return render_template('admin_dashboard.html')

@app.route('/students')
@login_required
def students_list():
    """学生列表页面"""
    # 检查用户类型，只有管理员可以访问
    if session.get('user_type') == 'student':
        flash('无权访问学生列表', 'error')
        return redirect(url_for('student_dashboard'))
    
    collection = get_students_collection()
    if collection is not None:
        students = list(collection.find().sort('created_at', -1))
        return render_template('index.html', students=students)
    else:
        flash('数据库连接失败', 'error')
        return render_template('index.html', students=[])

@app.route('/course-detail/<course_id>')
@login_required
def course_detail(course_id):
    """课程详情页面"""
    return render_template('course_detail.html')

@app.route('/edit-course/<course_id>')
@login_required
def edit_course(course_id):
    """编辑课程页面"""
    return render_template('edit_course.html')

@app.route('/api/courses', methods=['GET'])
def api_courses():
    """API接口 - 获取所有课程"""
    collection = get_courses_collection()
    if collection is not None:
        courses = list(collection.find().sort('course_code', 1))
        # 转换ObjectId为字符串
        for course in courses:
            course['_id'] = str(course['_id'])
        return jsonify(courses)
    return jsonify([])

@app.route('/api/courses/<course_id>', methods=['GET', 'PUT', 'DELETE'])
def api_course_detail(course_id):
    """API接口 - 获取单个课程详情、更新课程或删除课程"""
    if request.method == 'GET':
        collection = get_courses_collection()
        if collection is not None:
            try:
                course = collection.find_one({'_id': ObjectId(course_id)})
                if course:
                    course['_id'] = str(course['_id'])
                    return jsonify(course)
                else:
                    return jsonify({'error': '课程不存在'}), 404
            except Exception as e:
                return jsonify({'error': '无效的课程ID'}), 400
        return jsonify({'error': '数据库连接失败'}), 500
    
    elif request.method == 'PUT':
        try:
            data = request.get_json()
            if not data:
                return jsonify({'error': '请求数据为空'}), 400
            
            collection = get_courses_collection()
            if collection is None:
                return jsonify({'error': '数据库连接失败'}), 500
            
            # 检查课程是否存在
            course = collection.find_one({'_id': ObjectId(course_id)})
            if not course:
                return jsonify({'error': '课程不存在'}), 404
            
            # 更新课程数据
            update_data = {
                'course_code': data.get('course_code', course.get('course_code', '')),
                'course_name': data.get('course_name', course.get('course_name', '')),
                'credits': int(data.get('credits', course.get('credits', 0))),
                'teacher': data.get('teacher', course.get('teacher', '')),
                'schedule': data.get('schedule', course.get('schedule', '')),
                'location': data.get('location', course.get('location', '')),
                'capacity': int(data.get('capacity', course.get('capacity', 0))),
                'description': data.get('description', course.get('description', '')),
                'updated_at': datetime.now()
            }
            
            # 保留已选人数不变
            update_data['enrolled'] = course.get('enrolled', 0)
            
            # 更新数据库
            result = collection.update_one(
                {'_id': ObjectId(course_id)},
                {'$set': update_data}
            )
            
            if result.modified_count > 0:
                return jsonify({'message': '课程信息更新成功'})
            else:
                return jsonify({'message': '课程信息未发生变化'})
                
        except Exception as e:
            logger.error(f"更新课程错误: {str(e)}")
            return jsonify({'error': '服务器内部错误'}), 500
    
    elif request.method == 'DELETE':
        try:
            collection = get_courses_collection()
            if collection is None:
                return jsonify({'error': '数据库连接失败'}), 500
            
            # 检查课程是否存在
            course = collection.find_one({'_id': ObjectId(course_id)})
            if not course:
                return jsonify({'error': '课程不存在'}), 404
            
            # 检查是否有学生选了这门课程
            student_courses_collection = get_student_courses_collection()
            if student_courses_collection is None:
                return jsonify({'error': '数据库连接失败'}), 500
            
            # 检查是否有选课记录
            enrollment_count = student_courses_collection.count_documents({
                'course_id': ObjectId(course_id)
            })
            
            if enrollment_count > 0:
                return jsonify({
                    'error': '无法删除课程',
                    'message': f'该课程已有 {enrollment_count} 名学生选课，请先处理选课记录'
                }), 400
            
            # 删除课程
            result = collection.delete_one({'_id': ObjectId(course_id)})
            
            if result.deleted_count > 0:
                return jsonify({'message': '课程删除成功'})
            else:
                return jsonify({'error': '课程删除失败'}), 500
                
        except Exception as e:
            logger.error(f"删除课程错误: {str(e)}")
            return jsonify({'error': '服务器内部错误'}), 500

@app.route('/api/courses', methods=['POST'])
def api_add_course():
    """API接口 - 添加课程"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({'error': '请求数据为空'}), 400
        
        # 验证必填字段
        required_fields = ['course_code', 'course_name', 'credits']
        for field in required_fields:
            if field not in data or not data[field]:
                return jsonify({'error': f'缺少必要字段: {field}'}), 400
        
        # 创建课程数据
        course_data = {
            'course_code': data['course_code'],
            'course_name': data['course_name'],
            'credits': int(data['credits']),
            'teacher': data.get('teacher', ''),
            'schedule': data.get('schedule', ''),
            'location': data.get('location', ''),
            'capacity': int(data.get('capacity', 0)),
            'enrolled': int(data.get('enrolled', 0)),
            'description': data.get('description', ''),
            'created_at': datetime.now(),
            'updated_at': datetime.now()
        }
        
        # 插入数据库
        collection = get_courses_collection()
        if collection is not None:
            result = collection.insert_one(course_data)
            return jsonify({
                'message': '课程添加成功',
                'course_id': str(result.inserted_id)
            }), 201
        else:
            return jsonify({'error': '数据库连接失败'}), 500
            
    except Exception as e:
        logger.error(f"添加课程错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

# 管理员管理API
@app.route('/admin-management')
@admin_required
def admin_management():
    """管理员管理页面"""
    return render_template('admin_management.html')

@app.route('/api/admin-users', methods=['GET'])
@admin_required
def api_admin_users():
    """API接口 - 获取所有管理员"""
    collection = get_admin_users_collection()
    if collection is not None:
        admins = list(collection.find().sort('created_at', -1))
        # 转换ObjectId为字符串
        for admin in admins:
            admin['_id'] = str(admin['_id'])
        return jsonify(admins)
    return jsonify([])

@app.route('/api/admin-users', methods=['POST'])
@admin_required
def api_add_admin():
    """API接口 - 添加管理员"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({'error': '请求数据为空'}), 400
        
        # 验证必填字段
        required_fields = ['username', 'password', 'role']
        for field in required_fields:
            if field not in data or not data[field]:
                return jsonify({'error': f'缺少必要字段: {field}'}), 400
        
        # 检查用户名是否已存在
        collection = get_admin_users_collection()
        if collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        existing_admin = collection.find_one({'username': data['username']})
        if existing_admin:
            return jsonify({'error': '用户名已存在'}), 400
        
        # 创建管理员数据
        admin_data = {
            'username': data['username'],
            'password': hash_password(data['password']),
            'role': data['role'],
            'created_at': datetime.now(),
            'updated_at': datetime.now(),
            'last_login': None
        }
        
        result = collection.insert_one(admin_data)
        return jsonify({
            'message': '管理员添加成功',
            'admin_id': str(result.inserted_id)
        }), 201
        
    except Exception as e:
        logger.error(f"添加管理员错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

@app.route('/api/admin-users/<admin_id>', methods=['PUT'])
@admin_required
def api_update_admin(admin_id):
    """API接口 - 更新管理员信息"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({'error': '请求数据为空'}), 400
        
        collection = get_admin_users_collection()
        if collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        # 检查管理员是否存在
        admin = collection.find_one({'_id': ObjectId(admin_id)})
        if not admin:
            return jsonify({'error': '管理员不存在'}), 404
        
        # 构建更新数据
        update_data = {
            'updated_at': datetime.now()
        }
        
        if 'username' in data:
            # 检查用户名是否已被其他管理员使用
            existing_admin = collection.find_one({
                'username': data['username'],
                '_id': {'$ne': ObjectId(admin_id)}
            })
            if existing_admin:
                return jsonify({'error': '用户名已被其他管理员使用'}), 400
            update_data['username'] = data['username']
        
        if 'password' in data and data['password']:
            update_data['password'] = hash_password(data['password'])
        
        if 'role' in data:
            update_data['role'] = data['role']
        
        # 更新数据库
        result = collection.update_one(
            {'_id': ObjectId(admin_id)},
            {'$set': update_data}
        )
        
        if result.modified_count > 0:
            return jsonify({'message': '管理员信息更新成功'})
        else:
            return jsonify({'message': '管理员信息未发生变化'})
            
    except Exception as e:
        logger.error(f"更新管理员错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

@app.route('/api/admin-users/<admin_id>', methods=['DELETE'])
@admin_required
def api_delete_admin(admin_id):
    """API接口 - 删除管理员"""
    try:
        collection = get_admin_users_collection()
        if collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        # 检查管理员是否存在
        admin = collection.find_one({'_id': ObjectId(admin_id)})
        if not admin:
            return jsonify({'error': '管理员不存在'}), 404
        
        # 不能删除超级管理员
        if admin['role'] == 'super_admin':
            return jsonify({'error': '不能删除超级管理员'}), 400
        
        # 不能删除当前登录的管理员
        if str(admin['_id']) == session.get('user_id'):
            return jsonify({'error': '不能删除当前登录的管理员'}), 400
        
        # 删除管理员
        result = collection.delete_one({'_id': ObjectId(admin_id)})
        
        if result.deleted_count > 0:
            return jsonify({'message': '管理员删除成功'})
        else:
            return jsonify({'error': '管理员删除失败'}), 500
            
    except Exception as e:
        logger.error(f"删除管理员错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

@app.route('/change-password')
@login_required
def change_password():
    """修改密码页面"""
    return render_template('change_password.html')

@app.route('/api/change-password', methods=['POST'])
@login_required
def api_change_password():
    """API接口 - 修改密码（支持管理员和学生）"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({'error': '请求数据为空'}), 400
        
        required_fields = ['current_password', 'new_password', 'confirm_password']
        for field in required_fields:
            if field not in data or not data[field]:
                return jsonify({'error': f'缺少必要字段: {field}'}), 400
        
        # 验证新密码和确认密码是否一致
        if data['new_password'] != data['confirm_password']:
            return jsonify({'error': '新密码和确认密码不一致'}), 400
        
        # 验证新密码长度
        if len(data['new_password']) < 8:
            return jsonify({'error': '新密码长度不能少于8位'}), 400
        
        # 根据用户类型选择对应的集合
        user_type = session.get('user_type')
        user_id = session.get('user_id')
        
        if user_type == 'admin':
            collection = get_admin_users_collection()
        elif user_type == 'student':
            collection = get_student_auth_collection()
        else:
            return jsonify({'error': '未知的用户类型'}), 400
        
        if collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        # 获取当前用户信息
        user = collection.find_one({'_id': ObjectId(user_id)})
        if not user:
            return jsonify({'error': '用户不存在'}), 404
        
        # 验证当前密码
        if not check_password(data['current_password'], user['password']):
            return jsonify({'error': '当前密码不正确'}), 400
        
        # 更新密码
        result = collection.update_one(
            {'_id': ObjectId(user_id)},
            {'$set': {
                'password': hash_password(data['new_password']),
                'updated_at': datetime.now()
            }}
        )
        
        if result.modified_count > 0:
            return jsonify({'message': '密码修改成功'})
        else:
            return jsonify({'error': '密码修改失败'}), 500
            
    except Exception as e:
        logger.error(f"修改密码错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

# 选课功能
@app.route('/api/student-courses', methods=['GET'])
def api_all_student_courses():
    """API接口 - 获取所有学生的选课记录"""
    try:
        student_courses_collection = get_student_courses_collection()
        if student_courses_collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        # 获取所有选课记录
        student_courses = list(student_courses_collection.find())
        
        # 转换ObjectId为字符串
        for sc in student_courses:
            sc['_id'] = str(sc['_id'])
            sc['student_id'] = str(sc['student_id'])
            sc['course_id'] = str(sc['course_id'])
        
        return jsonify(student_courses)
        
    except Exception as e:
        logger.error(f"获取选课记录错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

@app.route('/api/student-courses/<student_id>', methods=['GET'])
@login_required
def api_student_courses(student_id):
    """API接口 - 获取学生的选课列表"""
    try:
        # 权限验证：学生只能查看自己的选课记录，管理员可以查看所有
        user_type = session.get('user_type')
        if user_type == 'student':
            # 学生只能查看自己的选课记录
            student_auth_collection = get_student_auth_collection()
            if student_auth_collection is None:
                return jsonify({'error': '数据库连接失败'}), 500
            
            # 获取当前登录学生的认证信息
            student_auth = student_auth_collection.find_one({'_id': ObjectId(session.get('user_id'))})
            if not student_auth:
                return jsonify({'error': '学生认证信息不存在'}), 404
            
            # 验证学生ID是否匹配
            if str(student_auth['student_id']) != student_id:
                return jsonify({'error': '无权查看其他学生的选课记录'}), 403
        
        student_courses_collection = get_student_courses_collection()
        if student_courses_collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        # 获取学生的选课记录
        student_courses = list(student_courses_collection.find(
            {'student_id': ObjectId(student_id)}
        ))
        
        # 获取课程详情
        courses_collection = get_courses_collection()
        if courses_collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        result = []
        for sc in student_courses:
            course = courses_collection.find_one({'_id': ObjectId(sc['course_id'])})
            if course:
                result.append({
                    'selection_id': str(sc['_id']),
                    'course_id': str(course['_id']),
                    'course_code': course['course_code'],
                    'course_name': course['course_name'],
                    'credits': course['credits'],
                    'teacher': course.get('teacher', ''),
                    'selected_at': sc['selected_at'],
                    'status': sc.get('status', '已选')
                })
        
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"获取学生选课列表错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

@app.route('/api/student-auth-info', methods=['GET'])
@login_required
def api_student_auth_info():
    """API接口 - 获取学生认证信息（用于获取对应的学生ID）"""
    try:
        user_type = session.get('user_type')
        user_id = session.get('user_id')
        
        if user_type != 'student':
            return jsonify({'error': '只有学生用户可以访问此信息'}), 403
        
        student_auth_collection = get_student_auth_collection()
        if student_auth_collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        # 获取学生认证信息
        student_auth = student_auth_collection.find_one({'_id': ObjectId(user_id)})
        if not student_auth:
            return jsonify({'error': '学生认证信息不存在'}), 404
        
        return jsonify({
            'student_id': str(student_auth['student_id']),
            'name': student_auth.get('name', ''),
            'username': student_auth.get('username', '')
        })
        
    except Exception as e:
        logger.error(f"获取学生认证信息错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

@app.route('/api/student-courses/<selection_id>', methods=['DELETE'])
def api_delete_student_course(selection_id):
    """API接口 - 删除学生选课记录（退课）"""
    try:
        student_courses_collection = get_student_courses_collection()
        if student_courses_collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        # 获取选课记录
        selection = student_courses_collection.find_one({'_id': ObjectId(selection_id)})
        if not selection:
            return jsonify({'error': '选课记录不存在'}), 404
        
        # 获取课程信息
        courses_collection = get_courses_collection()
        if courses_collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        # 删除选课记录
        result = student_courses_collection.delete_one({'_id': ObjectId(selection_id)})
        
        if result.deleted_count > 0:
            # 更新课程的已选人数
            courses_collection.update_one(
                {'_id': ObjectId(selection['course_id'])},
                {'$inc': {'enrolled': -1}}
            )
            
            return jsonify({'message': '退课成功'})
        else:
            return jsonify({'error': '退课失败'}), 500
            
    except Exception as e:
        logger.error(f"退课错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

@app.route('/api/selection', methods=['POST'])
@login_required
def api_select_course():
    """API接口 - 学生选课"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({'error': '请求数据为空'}), 400
        
        required_fields = ['student_id', 'course_id']
        for field in required_fields:
            if field not in data or not data[field]:
                return jsonify({'error': f'缺少必要字段: {field}'}), 400
        
        student_id = data['student_id']
        course_id = data['course_id']
        
        # 权限验证：学生只能为自己选课，管理员可以为任何学生选课
        user_type = session.get('user_type')
        if user_type == 'student':
            # 学生只能为自己选课
            student_auth_collection = get_student_auth_collection()
            if student_auth_collection is None:
                return jsonify({'error': '数据库连接失败'}), 500
            
            # 获取当前登录学生的认证信息
            student_auth = student_auth_collection.find_one({'_id': ObjectId(session.get('user_id'))})
            if not student_auth:
                return jsonify({'error': '学生认证信息不存在'}), 404
            
            # 验证学生ID是否匹配
            if str(student_auth['student_id']) != student_id:
                return jsonify({'error': '无权为其他学生选课'}), 403
        
        # 检查学生是否存在
        students_collection = get_students_collection()
        if students_collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        student = students_collection.find_one({'_id': ObjectId(student_id)})
        if not student:
            return jsonify({'error': '学生不存在'}), 404
        
        # 检查课程是否存在
        courses_collection = get_courses_collection()
        if courses_collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        course = courses_collection.find_one({'_id': ObjectId(course_id)})
        if not course:
            return jsonify({'error': '课程不存在'}), 404
        
        # 检查是否已经选过该课程
        student_courses_collection = get_student_courses_collection()
        if student_courses_collection is None:
            return jsonify({'error': '数据库连接失败'}), 500
        
        existing_selection = student_courses_collection.find_one({
            'student_id': ObjectId(student_id),
            'course_id': ObjectId(course_id)
        })
        
        if existing_selection:
            return jsonify({'error': '已经选过该课程'}), 400
        
        # 检查课程容量
        if course.get('capacity', 0) > 0 and course.get('enrolled', 0) >= course['capacity']:
            return jsonify({'error': '课程已满'}), 400
        
        # 创建选课记录
        selection_data = {
            'student_id': ObjectId(student_id),
            'course_id': ObjectId(course_id),
            'selected_at': datetime.now(),
            'status': '已选'
        }
        
        result = student_courses_collection.insert_one(selection_data)
        
        # 更新课程的已选人数
        courses_collection.update_one(
            {'_id': ObjectId(course_id)},
            {'$inc': {'enrolled': 1}}
        )
        
        return jsonify({
            'message': '选课成功',
            'selection_id': str(result.inserted_id)
        }), 201
        
    except Exception as e:
        logger.error(f"选课错误: {str(e)}")
        return jsonify({'error': '服务器内部错误'}), 500

if __name__ == '__main__':
    # 创建模板目录
    os.makedirs('templates', exist_ok=True)
    
    # 初始化超级管理员账号
    if init_super_admin():
        logger.info("超级管理员账号初始化成功")
    else:
        logger.error("超级管理员账号初始化失败")
    
    # 运行应用
    debug_mode = os.getenv('DEBUG', 'False').lower() == 'true'
    host = os.getenv('HOST', '0.0.0.0')
    port = int(os.getenv('PORT', 5001))
    
    app.run(debug=debug_mode, host=host, port=port)
